#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
#define LISTEN_PORT	9999
#define BACKLOG		13
typedef void *(THREAD_BODY)(void *thread_arg);



int thread_start(pthread_t *thread_id,THREAD_BODY * thread_workbody,void *thread_arg)
{
	int		rv=-1;
	pthread_attr_t	thread_attr;

	if(pthread_attr_init(&thread_attr))
	{
		printf("Phread_attr_init() failure: %s\n",strerror(errno));
		goto CleanUp;
	}

	if(pthread_attr_setstacksize(&thread_attr,120*1024))
	{
		printf("Phread_attr_setstacksize() failure: %s\n",strerror(errno));
		goto CleanUp;
	}
	if(pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED))
	{
		printf("Phread_attr_setdetachstate() failure:%s \n",strerror(errno));
		goto CleanUp;
	}
	//创建线程
	if(pthread_create(thread_id,&thread_attr,thread_workbody,thread_arg))
	{
		printf("Create thread failure: %s \n",strerror(errno));
		goto CleanUp;
	}
	rv=0;

CleanUp:
	//销毁程序
	pthread_attr_destroy(&thread_attr);
	return rv;
}


void *thread_worker(int  *ctx)
{
	int	cli_fd=-1;
	int	rv=-1;
	char 	buf[1024];

	cli_fd=(int)ctx;
	
	printf("Pthread start to communicate with socket client.\n");
	while(1)
	{
		memset(buf,0,sizeof(buf));
		rv=read(cli_fd,buf,sizeof(buf));
		if(rv<0)
		{
			printf("Read data from client in socket[%d] failure!\n",cli_fd);
			pthread_exit(NULL);
		}
		else if(0==rv)
		{
			printf("Client get disconnected!\n");
			pthread_exit(NULL);
		}
		printf("Read data %d bytes : %s from sock[%d]!\n",rv,buf,cli_fd);

		if(write(cli_fd,buf,rv)<0)
		{
			printf("Write back to client socket[%d] failure:%s!\n",cli_fd,strerror(errno));
			pthread_exit(NULL);
		}
		printf("Write to client socket[%d] successfully!\n",cli_fd);
		sleep(1);
		close(cli_fd);
		pthread_exit(NULL);
	}
}
int main(int argc,char **argv)
{
	int 			listen_fd=-1;
	int 			cli_fd=-1;
	struct sockaddr_in	serv_addr;
	struct sockaddr_in	cli_addr;
	socklen_t		cliaddr_len;
	pthread_t		tid;

	//服务器端 首先创建socket  ipv4 tcp 0
	listen_fd=socket(AF_INET,SOCK_STREAM,0);
	if(listen_fd<0)
	{
		printf("Create a socket failure: %s!\n",strerror(errno));
		return -1;
	}
	printf("Create a socket[%d] successfully!\n",listen_fd);

	//第二步，重置服务器端的数据 为什么这里求大小用的是指针呢？
	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_port=htons(LISTEN_PORT);
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);

	//第三步步 bind
	if((bind(listen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0))
	{
		printf("Create a socket[%d] failure: %s!\n",listen_fd,strerror(errno));
		return -2;
	}
	printf("Socket[%d] bind on port[%d] for all IP ok!\n",listen_fd,LISTEN_PORT);
	
	//第四步 服务器监听
	listen(listen_fd,BACKLOG);
	while(1)
	{
		printf("Waiting for client to connect...\n");
		cli_fd=accept(listen_fd,(struct sockaddr*)&cli_addr,&cliaddr_len);
		if(cli_fd<0)
		{
			printf("Connect to client failure!\n");
			return -3;
		}
		printf("Connect to client[%s:%d] on socket[%d] successfully!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),listen_fd);
		
		//创建线程
		thread_start(&tid,thread_worker,(void *)cli_fd);
	
	}
	close(listen_fd);

}
